package net.flashpunk.utils 
{
	/**
	 * Static class with useful easer functions that can be used by Tweens.
	 */
	public class Ease 
	{
		/** Quadratic in. */
		public static function quadIn(t:Number):Number
		{
			return t * t;
		}
		
		/** Quadratic out. */
		public static function quadOut(t:Number):Number
		{
			return -t * (t - 2);
		}
		
		/** Quadratic in and out. */
		public static function quadInOut(t:Number):Number
		{
			return t <= .5 ? t * t * 2 : 1 - (--t) * t * 2;
		}
		
		/** Cubic in. */
		public static function cubeIn(t:Number):Number
		{
			return t * t * t;
		}
		
		/** Cubic out. */
		public static function cubeOut(t:Number):Number
		{
			return 1 + (--t) * t * t;
		}
		
		/** Cubic in and out. */
		public static function cubeInOut(t:Number):Number
		{
			return t <= .5 ? t * t * t * 4 : 1 + (--t) * t * t * 4;
		}
		
		/** Quart in. */
		public static function quartIn(t:Number):Number
		{
			return t * t * t * t;
		}
		
		/** Quart out. */
		public static function quartOut(t:Number):Number
		{
			return 1 - (t-=1) * t * t * t;
		}
		
		/** Quart in and out. */
		public static function quartInOut(t:Number):Number
		{
			return t <= .5 ? t * t * t * t * 8 : (1 - (t = t * 2 - 2) * t * t * t) / 2 + .5;
		}
		
		/** Quint in. */
		public static function quintIn(t:Number):Number
		{
			return t * t * t * t * t;
		}
		
		/** Quint out. */
		public static function quintOut(t:Number):Number
		{
			return (t = t - 1) * t * t * t * t + 1;
		}
		
		/** Quint in and out. */
		public static function quintInOut(t:Number):Number
		{
			return ((t *= 2) < 1) ? (t * t * t * t * t) / 2 : ((t -= 2) * t * t * t * t + 2) / 2;
		}
		
		/** Sine in. */
		public static function sineIn(t:Number):Number
		{
			return -Math.cos(PI2 * t) + 1;
		}
		
		/** Sine out. */
		public static function sineOut(t:Number):Number
		{
			return Math.sin(PI2 * t);
		}
		
		/** Sine in and out. */
		public static function sineInOut(t:Number):Number
		{
			return -Math.cos(PI * t) / 2 + .5;
		}
		
		/** Bounce in. */
		public static function bounceIn(t:Number):Number
		{
			t = 1 - t;
			if (t < B1) return 1 - 7.5625 * t * t;
			if (t < B2) return 1 - (7.5625 * (t - B3) * (t - B3) + .75);
			if (t < B4) return 1 - (7.5625 * (t - B5) * (t - B5) + .9375);
			return 1 - (7.5625 * (t - B6) * (t - B6) + .984375);
		}
		
		/** Bounce out. */
		public static function bounceOut(t:Number):Number
		{
			if (t < B1) return 7.5625 * t * t;
			if (t < B2) return 7.5625 * (t - B3) * (t - B3) + .75;
			if (t < B4) return 7.5625 * (t - B5) * (t - B5) + .9375;
			return 7.5625 * (t - B6) * (t - B6) + .984375;
		}
		
		/** Bounce in and out. */
		public static function bounceInOut(t:Number):Number
		{
			if (t < .5)
			{
				t = 1 - t * 2;
				if (t < B1) return (1 - 7.5625 * t * t) / 2;
				if (t < B2) return (1 - (7.5625 * (t - B3) * (t - B3) + .75)) / 2;
				if (t < B4) return (1 - (7.5625 * (t - B5) * (t - B5) + .9375)) / 2;
				return (1 - (7.5625 * (t - B6) * (t - B6) + .984375)) / 2;
			}
			t = t * 2 - 1;
			if (t < B1) return (7.5625 * t * t) / 2 + .5;
			if (t < B2) return (7.5625 * (t - B3) * (t - B3) + .75) / 2 + .5;
			if (t < B4) return (7.5625 * (t - B5) * (t - B5) + .9375) / 2 + .5;
			return (7.5625 * (t - B6) * (t - B6) + .984375) / 2 + .5;
		}
		
		/** Circle in. */
		public static function circIn(t:Number):Number
		{
			return -(Math.sqrt(1 - t * t) - 1);
		}
		
		/** Circle out. */
		public static function circOut(t:Number):Number
		{
			return Math.sqrt(1 - (t - 1) * (t - 1));
		}
		
		/** Circle in and out. */
		public static function circInOut(t:Number):Number
		{
			return t <= .5 ? (Math.sqrt(1 - t * t * 4) - 1) / -2 : (Math.sqrt(1 - (t * 2 - 2) * (t * 2 - 2)) + 1) / 2;
		}
		
		/** Exponential in. */
		public static function expoIn(t:Number):Number
		{
			return Math.pow(2, 10 * (t - 1));
		}
		
		/** Exponential out. */
		public static function expoOut(t:Number):Number
		{
			return -Math.pow(2, -10 * t) + 1;
		}
		
		/** Exponential in and out. */
		public static function expoInOut(t:Number):Number
		{
			return t < .5 ? Math.pow(2, 10 * (t * 2 - 1)) / 2 : (-Math.pow(2, -10 * (t * 2 - 1)) + 2) / 2;
		}
		
		/** Back in. */
		public static function backIn(t:Number):Number
		{
			return t * t * (2.70158 * t - 1.70158);
		}
		
		/** Back out. */
		public static function backOut(t:Number):Number
		{
			return 1 - (--t) * (t) * (-2.70158 * t - 1.70158);
		}
		
		/** Back in and out. */
		public static function backInOut(t:Number):Number
		{
			t *= 2;
			if (t < 1) return t * t * (2.70158 * t - 1.70158) / 2;
			t --;
			return (1 - (--t) * (t) * (-2.70158 * t - 1.70158)) / 2 + .5;
		}
		
		// Easing constants.
		/** @private */ private static const PI:Number = Math.PI;
		/** @private */ private static const PI2:Number = Math.PI / 2;
		/** @private */ private static const EL:Number = 2 * PI / .45;
		/** @private */ private static const B1:Number = 1 / 2.75;
		/** @private */ private static const B2:Number = 2 / 2.75;
		/** @private */ private static const B3:Number = 1.5 / 2.75;
		/** @private */ private static const B4:Number = 2.5 / 2.75;
		/** @private */ private static const B5:Number = 2.25 / 2.75;
		/** @private */ private static const B6:Number = 2.625 / 2.75;
		
		/**
		 * Operation of in/out easers:
		 * 
		 * in(t)
		 *		return t;
		 * out(t)
		 * 		return 1 - in(1 - t);
		 * inOut(t)
		 * 		return (t <= .5) ? in(t * 2) / 2 : out(t * 2 - 1) / 2 + .5;
		 */
	}
}
